unit unitGDIPlusObjs;

{$IFDEF FPC}
{$H+}
{$MODE DELPHI}
{$ENDIF}

interface

uses Windows, ActiveX, unitGDIPlusFlat, unitGDIPlus, unitCommonTypes;

type
  TGPGraphics = class;

  TGpBrush = class(TGdiPlusObj)
  protected
    procedure DoFreeInnerObj; override;
    function DoClone(var Obj: Pointer): TGpStatus; override;
  public
  end;

  TGpSolidBrush = class(TGpBrush)
  private
    function GetColor: TARGB;
    procedure SetColor(const Value: TARGB);
  public
    procedure CreateBrush(color: TARGB);

    property color: TARGB read GetColor write SetColor;
  end;

  TGpLineBrush = class(TGpBrush)
  private
    function GetLineRect: TGpRectF;
    function GetLineRectI: TGpRect;
    function GetLineGammaCorrection: boolean;
    procedure SetLineGammaCorrection(const Value: boolean);
    function GetLineBlendCount: integer;
    function GetLineWrapMode: TGpWrapMode;
    procedure SetLineWrapMode(const Value: TGpWrapMode);
    function GetLineTransform: TGpMatrix;
    procedure SetLineTransform(const Value: TGpMatrix);
  public
    procedure CreateLineBrush(const point1, point2: TGpPointF; color1, color2: TARGB; wrapMode: TGpWrapMode); overload;
    procedure CreateLineBrush(const point1, point2: TGpPoint; color1, color2: TARGB; wrapMode: TGpWrapMode); overload;
    procedure CreateLineBrushFromRect(const rect: TGpRectF; color1, color2: TARGB;
      mode: TLinearGradientMode; wrapMode: TGpWrapMode);
    procedure CreateLineBrushFromRectI(const rect: TGpRect; color1, color2: TARGB;
      mode: TLinearGradientMode; wrapMode: TGpWrapMode);
    procedure CreateLineBrushFromRectWithAngle(const rect: TGpRectF; color1, color2: TARGB;
      angle: single; isAngleScalable: boolean; wrapMode: TGpWrapMode);
    procedure CreateLineBrushFromRectWithAngleI(const rect: TGpRect; color1, color2: TARGB;
      angle: single; isAngleScalable: boolean; wrapMode: TGpWrapMode);

    procedure SetLineColors(color1, color2: TARGB);
    function GetLineColors: TARGB;
    procedure GetLineBlend(var blend, positions: single; Count: integer);
    procedure SetLineBlend(const blend, positions: single; Count: integer);

    property LineRect: TGpRectF read GetLineRect;
    property LineRectI: TGpRect read GetLineRectI;
    property LineBlendCount: integer read GetLineBlendCount;
    property LineGammaCorrection: boolean read GetLineGammaCorrection write SetLineGammaCorrection;
    property LineWrapMode: TGpWrapMode read GetLineWrapMode write SetLineWrapMode;
    property LineTransform: TGpMatrix read GetLineTransform write SetLineTransform;
  end;

  TGpPen = class(TGdiPlusObj)
  private
    function GetPenWidth: single;
    procedure SetPenWidth(const Value: single);
    function GetPenUnit: TUnit;
    procedure SetPenUnit(const Value: TUnit);
    function GetPenStartCap: TGpLineCap;
    procedure SetPenStartCap(const Value: TGpLineCap);
    function GetPenEndCap: TGpLineCap;
    procedure SetPenEndCap(const Value: TGpLineCap);
    function GetPenDashCap197819: TGpDashCap;
    procedure SetPenDashCap197819(const Value: TGpDashCap);
    function GetPenLineJoin: TGpLineJoin;
    procedure SetPenLineJoin(const Value: TGpLineJoin);
    function GetCustomStartCap: TGpCustomLineCap;
    procedure SetCustomStartCap(const Value: TGpCustomLineCap);
  protected
    procedure DoFreeInnerObj; override;
    function DoClone(var Obj: Pointer): TGpStatus; override;
  public
    procedure CreatePen1(color: TARGB; Width: single; u: TUnit = UnitWorld);
    procedure CreatePen2(brush: TGpBrush; Width: single; u: TUnit = UnitWorld);

    property PenWidth: single read GetPenWidth write SetPenWidth;
    property PenUnit: TUnit read GetPenUnit write SetPenUnit;
    // property PenLineCap197819:
    property PenStartCap: TGpLineCap read GetPenStartCap write SetPenStartCap;
    property PenEndCap: TGpLineCap read GetPenEndCap write SetPenEndCap;
    property PenDashCap197819: TGpDashCap read GetPenDashCap197819 write SetPenDashCap197819;
    property PenLineJoin: TGpLineJoin read GetPenLineJoin write SetPenLineJoin;
    property PenCustomStartCap: TGpCustomLineCap read GetCustomStartCap write SetCustomStartCap;
  end;

  TGpImage = class(TGdiPlusObj)
  private
    // FGraphic: TGPGraphics;
    FImageCount: integer;
    FImageGUID: TGUID;
    FImageDelays: PPROPERTY_ITEM;
    FImageActiveFrame: integer;
    FWidth, FHeight: longword;
    FLockedData: TBitmapData;
    FBytePerPix: longword;
    FPropertyIDs: array of longword;

    function GetImageCount: integer;
    function GetImageFlags: UINT;
    function GetImageType: TImageType;
    function GetImageHeight: UINT;
    function GetImageWidth: UINT;
    function GetImageHorizontalResolution: single;
    function GetImageVerticalResolution: single;
    function GetImageRawFormat: TGUID;
    function GetImagePixelFormat: TPixelFormat;
    procedure GetImageFrameCount;
    function GetImageDelay(Index: integer): integer;
    procedure SetImageActiveFrame(const Value: integer);
    function GetLocked: boolean;
    function GetPixel(X, Y: longword): TARGB;
    function GetImageBuf: pchar;
    function GetImageStride: longword;
    procedure GetImageInfo;
    function GetLockData: PBitmapData;
    function GetPixIncrement: longword;
    function GetPropertyCount: longword;
    function GetPropertyID(Index: integer): longword;
    function GetRotateFlipType: TRotateFlipType;
    procedure SetRotateFlipType(const Value: TRotateFlipType);
  protected
    procedure DoFreeInnerObj; override;
    function DoClone(var Obj: Pointer): TGpStatus; override;
  public
    procedure LoadImageFromStream(stream: IStream);
    procedure LoadImageFromFile(filename: string);
    procedure LoadImageFromStreamICM(stream: IStream);
    procedure LoadImageFromFileICM(filename: string);
    procedure CreateBitmap(Width, Height, stride: integer; format: TPixelFormat; scan0: pbyte); overload;
    procedure CreateBitmap(Width, Height: integer; format: TPixelFormat = PixelFormat32bppARGB); overload;
    procedure CreateBitmap(Width, Height: integer; target: TGPGraphics); overload;
    procedure CreateBitmap(const bmi: TBITMAPINFO; gdiBitMapData: Pointer); overload;
    procedure CreateBitmap(hbm: HBITMAP; hpal: HPALETTE); overload;
    procedure DisposeImage;
    function SaveImageToFile(filename: string; const clsidEncoder: TGUID;
      encoderParams: PEncoderParameters = nil): boolean;

    procedure BitmapLockBits(const rect: TGpRect; flags: UINT; format: TPixelFormat;
      var lockedBitmapData: TBitmapData);
    procedure BitmapUnlockBits(const lockedBitmapData: TBitmapData);
    procedure RotateFlip(rfType: TRotateFlipType);
    function LockImage: boolean;
    procedure UnLockImage;
    function GetPropertyValue(PID: longword; var Len: longword): Pointer;

    property Locked: boolean read GetLocked;
    property Pixel[X, Y: longword]: TARGB read GetPixel;
    property LockData: PBitmapData read GetLockData;
    property PixIncrement: longword read GetPixIncrement;
    property ImageStride: longword read GetImageStride;
    property ImageBuf: pchar read GetImageBuf;
    property ImageType: TImageType read GetImageType;
    property ImageFlags: UINT read GetImageFlags;
    property ImageWidth: UINT read GetImageWidth;
    property ImageHeight: UINT read GetImageHeight;
    property ImageHorizontalResolution: single read GetImageHorizontalResolution;
    property ImageVerticalResolution: single read GetImageVerticalResolution;
    property ImageRawFormat: TGUID read GetImageRawFormat;
    property ImagePixelFormat: TPixelFormat read GetImagePixelFormat;
    property ImageCount: integer read GetImageCount;
    property ImageDelay[Index: integer]: integer read GetImageDelay;
    property ImageActiveFrame: integer read FImageActiveFrame write SetImageActiveFrame;
    property RotateFlipType: TRotateFlipType read GetRotateFlipType write SetRotateFlipType;
    property PropertyCount: longword read GetPropertyCount;
    property PropertyID[index: integer]: longword read GetPropertyID;
  end;

  TGpBitmap = class(TGdiPlusObj)
  private
    // FHandle: HBITMAP;
    function GetPixel(X, Y: integer): TARGB;
    procedure SetPixel(X, Y: integer; const Value: TARGB);
    function GetHandle: HBITMAP;
  protected
  public
    procedure CreateBitmap(Width, Height: integer; format: TPixelFormat = PixelFormat32bppARGB);
    procedure CreateBitmapFromStream(stream: IStream);
    procedure CreateBitmapFromFile(filename: string);
    procedure CreateBitmapFromStreamICM(stream: IStream);
    procedure CreateBitmapFromFileICM(filename: string);
    procedure CreateBitmapFromScan0(Width, Height, stride: integer; format: TPixelFormat; scan0: pbyte);
    procedure CreateBitmapFromGraphics(Width, Height: integer; target: TGPGraphics);
    procedure CreateBitmapFromDirectDrawSurface(surface: IDirectDrawSurface7);
    procedure CreateBitmapFromGdiDib(const gdiBitmapInfo: BITMAPINFO; gdiBitMapData: Pointer);
    procedure CreateBitmapFromHBITMAP(hbm: HBITMAP; hpal: HPALETTE);
    function CreateHBITMAPFromBitmap(background: TARGB): HBITMAP;
    procedure CreateBitmapFromHICON(hicon: hicon);
    function CreateHICONFromBitmap: hicon;
    procedure CreateBitmapFromResource(hInstance: THandle; lpBitmapName: string);
    function CloneBitmapArea(X, Y, Width, Height: single; format: TPixelFormat): TGpBitmap;
    function CloneBitmapAreaI(X, Y, Width, Height: integer; format: TPixelFormat): TGpBitmap;
    procedure BitmapLockBits(const rect: TGpRect; flags: UINT; format: TPixelFormat; lockedBitmapData: TBitmapData);
    procedure BitmapUnlockBits(lockedBitmapData: TBitmapData);

    property Handle: HBITMAP read GetHandle;
    property Pixel[X, Y: integer]: TARGB read GetPixel write SetPixel;
  end;

  TGpFont = class(TGdiPlusObj)
  private
    function GetFontFamily: TGpFontFamily;
    function GetFontStyle: integer;
    function GetFontSize: single;
    function GetFontUnit: TUnit;
    function GetFontHeight(g: TGPGraphics): single;
    function GetFontHeightGivenDPI(dpi: single): single;
  protected
    function DoClone(var Obj: Pointer): TGpStatus; override;
    procedure DoFreeInnerObj; override;
  public
    procedure CreateFont(fontFamily: TGpFontFamily; emSize: single; style: integer; u: TUnit); overload;
    procedure CreateFromDC(dc: HDC);
    procedure CreateFontFromLogfont(dc: HDC; const logfont: LOGFONTW);
    procedure CreateFont(FontName: string; dc: HDC; Height: integer; Weight: integer = 400); overload;
    procedure GetLogFont(g: TGPGraphics; var logfont: LOGFONTA); overload;
    procedure GetLogFont(g: TGPGraphics; var logfont: LOGFONTW); overload;

    property fontFamily: TGpFontFamily read GetFontFamily;
    property FontStyle: integer read GetFontStyle;
    property FontSize: single read GetFontSize;
    property FontUnit: TUnit read GetFontUnit;
    property FontHeight[g: TGPGraphics]: single read GetFontHeight;
    property FondHeightGivenDPI[dpi: single]: single read GetFontHeightGivenDPI;
  end;

  TGpStringFormat = class(TGdiPlusObj)
  private
    function GetFlags: integer;
    procedure SetFlags(const Value: integer);
    function GetAlign: TStringAlignment;
    procedure SetAlign(const Value: TStringAlignment);
    function GetLineAlign: TStringAlignment;
    procedure SetLineAlign(const Value: TStringAlignment);
    function GetTrimming: TStringTrimming;
    procedure SetTrimming(const Value: TStringTrimming);
    function GetHotkeyPrefix: integer;
    procedure SetHotkeyPrefix(const Value: integer);
    function GetTabStopCount: integer;
  protected
    function DoClone(var Obj: Pointer): TGpStatus; override;
    procedure DoFreeInnerObj; override;
  public
    procedure CreateStringFormat(formatAttributes: integer; language: LANGID);
    procedure StringFormatGetGenericDefault;
    procedure StringFormatGetGenericTypographic;

    property flags: integer read GetFlags write SetFlags;
    property Align: TStringAlignment read GetAlign write SetAlign;
    property LineAlign: TStringAlignment read GetLineAlign write SetLineAlign;
    property Trimming: TStringTrimming read GetTrimming write SetTrimming;
    property HotkeyPrefix: integer read GetHotkeyPrefix write SetHotkeyPrefix;
    property TabStopCount: integer read GetTabStopCount;
  end;

  TGPImageAttributes = class(TGdiPlusObj)
  protected
    function DoClone(var Obj: Pointer): TGpStatus; override;
    procedure DoFreeInnerObj; override;
  public
    constructor Create; reintroduce; overload;
    function SetToIdentity(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ResetImageAttributes(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetColorMatrix(const colorMatrix: TColorMatrix; mode: TColorMatrixFlags = ColorMatrixFlagsDefault;
      type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearColorMatrix(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetColorMatrices(const colorMatrix: TColorMatrix; const grayMatrix: TColorMatrix;
      mode: TColorMatrixFlags = ColorMatrixFlagsDefault;
      type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearColorMatrices(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetThreshold(threshold: single; type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearThreshold(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetGamma(gamma: single; type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearGamma(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetNoOp(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearNoOp(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetColorKey(colorLow, colorHigh: TGPColor; type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearColorKey(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetOutputChannel(channelFlags: TColorChannelFlags;
      type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearOutputChannel(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetOutputChannelColorProfile(colorProfileFilename: widestring;
      type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearOutputChannelColorProfile(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetRemapTable(mapSize: cardinal; map: PColorMap;
      type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function ClearRemapTable(type_: TColorAdjustType = TColorAdjustType.Default): TGpStatus;
    function SetBrushRemapTable(mapSize: cardinal; map: PColorMap): TGpStatus;
    function ClearBrushRemapTable: TGpStatus;
    function SetWrapMode(wrap: TWrapMode; color: TGPColor; clamp: BOOL = False): TGpStatus;
    // The flags of the palette are ignored.
    function GetAdjustedPalette(colorPalette: PColorPalette; colorAdjustType: TColorAdjustType): TGpStatus;
  end;

  TGPGraphics = class(TGdiPlusObj)
  private
    function GetCompositingMode: TCompositingMode;
    procedure SetCompositingMode(const Value: TCompositingMode);
    function GetCompositingQuality: TCompositingQuality;
    procedure SetCompositingQuality(const Value: TCompositingQuality);
    function GetSmoothingMode: TSmoothingMode;
    procedure SetSmoothingMode(const Value: TSmoothingMode);
    function GetPixelOffsetMode: TPixelOffsetMode;
    procedure SetPixelOffsetMode(const Value: TPixelOffsetMode);
    function GetTextRenderingHint: TTextRenderingHint;
    procedure SetTextRenderingHint(const Value: TTextRenderingHint);
    function GetTextContrast: UINT;
    procedure SetTextContrast(const Value: UINT);
    function GetInterpolationMode: TInterpolationMode;
    procedure SetInterpolationMode(const Value: TInterpolationMode);
    function GetPageUnit: TUnit;
    procedure SetPageUnit(const Value: TUnit);
    function GetPageScale: single;
    procedure SetPageScale(const Value: single);
    function GetDpiX: single;
    function GetDpiY: single;
  protected
    procedure DoFreeInnerObj; override;
  public
    procedure CreateFromHDC(HDC: HDC);
    procedure CreateFromHDC2(HDC: HDC; device: THandle);
    procedure CreateFromWnd(hwnd: hwnd);
    procedure CreateFromHWNDICM(hwnd: hwnd);
    procedure CreateFromImage(image: TGpImage);

    function GetDC: HDC;
    procedure ReleaseDC(HDC: HDC);
    procedure GetRenderingOrigin(var X, Y: integer);
    procedure SetRenderingOrigin(X, Y: integer);
    procedure ResetWorldTransform;
    procedure ResetPageTransform;
    procedure MeasureString(s: string; font: TGpFont; const layoutRect: TRectF;
      stringFormat: TGpStringFormat; var boundingBox: TRectF);

    procedure DrawLine(pen: TGpPen; x1, y1, x2, y2: single); overload;
    procedure DrawLine(pen: TGpPen; x1, y1, x2, y2: integer); overload;
    procedure DrawLines(pen: TGpPen; const points: TGpPointF; Count: integer); overload;
    procedure DrawLines(pen: TGpPen; const points: TGpPoint; Count: integer); overload;
    procedure DrawArc(pen: TGpPen; X, Y, Width, Height, startAngle, sweepAngle: single); overload;
    procedure DrawArc(pen: TGpPen; X, Y, Width, Height: integer; startAngle, sweepAngle: single); overload;
    procedure DrawBezier(pen: TGpPen; x1, y1, x2, y2, x3, y3, x4, y4: single); overload;
    procedure DrawBezier(pen: TGpPen; x1, y1, x2, y2, x3, y3, x4, y4: integer); overload;
    procedure DrawBeziers(pen: TGpPen; const points: TGpPointF; Count: integer); overload;
    procedure DrawBeziers(pen: TGpPen; const points: TGpPoint; Count: integer); overload;
    procedure DrawRectangle(pen: TGpPen; r: TCommonRect); overload;
    procedure DrawRectangle(pen: TGpPen; X, Y, Width, Height: single); overload;
    procedure DrawRectangle(pen: TGpPen; X, Y, Width, Height: integer); overload;
    procedure DrawRectangles(pen: TGpPen; const points: TGpRectF; Count: integer); overload;
    procedure DrawRectangles(pen: TGpPen; const points: TGpRect; Count: integer); overload;
    procedure DrawEllipse(pen: TGpPen; X, Y, Width, Height: single); overload;
    procedure DrawEllipse(pen: TGpPen; X, Y, Width, Height: integer); overload;
    procedure DrawPie(pen: TGpPen; X, Y, Width, Height, startAngle, sweepAngle: single); overload;
    procedure DrawPie(pen: TGpPen; X, Y, Width, Height: integer; startAngle, sweepAngle: single); overload;
    procedure DrawPolygon(pen: TGpPen; const points: TGpPointF; Count: integer); overload;
    procedure DrawPolygon(pen: TGpPen; const points: TGpPoint; Count: integer); overload;
    procedure DrawCurve(pen: TGpPen; const points: TGpPointF; Count: integer); overload;
    procedure DrawCurve(pen: TGpPen; const points: TGpPoint; Count: integer); overload;
    procedure DrawCurve2(pen: TGpPen; const points: TGpPointF; Count: integer; tension: single); overload;
    procedure DrawCurve2(pen: TGpPen; const points: TGpPoint; Count: integer; tension: single); overload;
    procedure DrawCurve3(pen: TGpPen; const points: TGpPointF; Count, offset, numberOfSegments: integer;
      tension: single); overload;
    procedure DrawCurve3(pen: TGpPen; const points: TGpPoint; Count, offset, numberOfSegments: integer;
      tension: single); overload;
    procedure DrawClosedCurve(pen: TGpPen; const points: TGpPointF; Count: integer); overload;
    procedure DrawClosedCurve(pen: TGpPen; const points: TGpPoint; Count: integer); overload;
    procedure DrawCloseCurve2(pen: TGpPen; const points: TGpPointF; Count: integer; tension: single); overload;
    procedure DrawCloseCurve2(pen: TGpPen; const points: TGpPoint; Count: integer; tension: single); overload;
    procedure GraphicsClear(color: TARGB);
    procedure FillRectangle(brush: TGpBrush; X, Y, Width, Height: single); overload;
    procedure FillRectangle(brush: TGpBrush; X, Y, Width, Height: integer); overload;
    procedure FillRectangles(brush: TGpBrush; const rects: TGpRectF; Count: integer); overload;
    procedure FillRectangles(brush: TGpBrush; const rects: TGpRect; Count: integer); overload;
    procedure FillPolygon(brush: TGpBrush; const points: TGpPointF; Count: integer; fillMode: TGpFillMode); overload;
    procedure FillPolygon(brush: TGpBrush; const points: TGpPoint; Count: integer; fillMode: TGpFillMode); overload;
    procedure FillPolygon(brush: TGpBrush; const points: TGpRectF; Count: integer); overload;
    procedure FillPolygon(brush: TGpBrush; const points: TGpRect; Count: integer); overload;
    procedure FillEllipse(brush: TGpBrush; X, Y, Width, Height: single); overload;
    procedure FillEllipse(brush: TGpBrush; X, Y, Width, Height: integer); overload;
    procedure FillPie(brush: TGpBrush; X, Y, Width, Height, startAngle, sweepAngle: single); overload;
    procedure FillPie(brush: TGpBrush; X, Y, Width, Height: integer; startAngle, sweepAngle: single); overload;
    procedure FillClosedCurve(brush: TGpBrush; const points: TGpPointF; Count: integer); overload;
    procedure FillClosedCurve(brush: TGpBrush; const points: TGpPoint; Count: integer); overload;
    procedure FillClosedCurve2(brush: TGpBrush; const points: TGpPointF; Count: integer;
      tension: single; fillMode: TGpFillMode); overload;
    procedure FillClosedCurve2(brush: TGpBrush; const points: TGpPoint; Count: integer;
      tension: single; fillMode: TGpFillMode); overload;
    procedure DrawImage(image: TGpImage; X, Y: single); overload;
    procedure DrawImage(image: TGpImage; X, Y: integer); overload;
    procedure DrawImage(image: TGpImage; X, Y, Width, Height: single); overload;
    procedure DrawImage(image: TGpImage; X, Y, Width, Height: integer); overload;
    procedure DrawImage(image: TGpImage; const dstpoints: TGpPointF; Count: integer); overload;
    procedure DrawImage(image: TGpImage; const dstpoints: TGpPoint; Count: integer); overload;
    procedure DrawImage(image: TGpImage; X, Y, srcx, srcy, srcwidth, srcheight: single;
      srcUnit: TUnit = UnitPixel); overload;
    procedure DrawImage(image: TGpImage; X, Y, srcx, srcy, srcwidth, srcheight: integer;
      srcUnit: TUnit = UnitPixel); overload;
    procedure DrawImage(image: TGpImage; dst: TGpRect; srcx, srcy, srcwidth, srcheight: integer;
      imageAttributes: TGPImageAttributes; srcUnit: TUnit = UnitPixel); overload;
    procedure DrawString(s: string; font: TGpFont; const layoutRect: TRectF; stringFormat: TGpStringFormat;
      brush: TGpBrush);
    function StringWidth(s: string; font: TGpFont; const layoutRect: TRectF; stringFormat: TGpStringFormat): single;

    property CompositingMode: TCompositingMode read GetCompositingMode write SetCompositingMode;
    property CompositingQuality: TCompositingQuality read GetCompositingQuality write SetCompositingQuality;
    property SmoothingMode: TSmoothingMode read GetSmoothingMode write SetSmoothingMode;
    property PixelOffsetMode: TPixelOffsetMode read GetPixelOffsetMode write SetPixelOffsetMode;
    property TextRenderingHint: TTextRenderingHint read GetTextRenderingHint write SetTextRenderingHint;
    property TextContrast: UINT read GetTextContrast write SetTextContrast;
    property InterpolationMode: TInterpolationMode read GetInterpolationMode write SetInterpolationMode;
    property PageUnit: TUnit read GetPageUnit write SetPageUnit;
    property PageScale: single read GetPageScale write SetPageScale;
    property DpiX: single read GetDpiX;
    property DpiY: single read GetDpiY;
  end;

implementation

uses unitMisc;

function GetEncoderClsid(format: string; var pClsid: TGUID): boolean;
var
  num, size: longword;
  pimgci: PImageCodecInfo;
begin
  num := 0;
  size := 0;
  Result := False;

  GdipGetImageEncodersSize(num, size);
  if size > 0 then
  begin
    GetMem(pimgci, size);
    if pimgci <> nil then
    begin
      GdipGetImageEncoders(num, size, pimgci^);

      while num > 0 do
      begin
        if pimgci.MimeType = format then
        begin
          Move(pimgci.ClassID, pClsid, SizeOf(TGUID));
          Result := True;
        end;
        Inc(pimgci);
        Dec(num);
      end;
      FreeMem(pimgci);
    end;
  end;
end;

{ TGPGraphics }

procedure TGPGraphics.CreateFromHDC(HDC: HDC);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFromHDC(HDC, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGPGraphics.CreateFromHDC2(HDC: HDC; device: THandle);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFromHDC2(HDC, device, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGPGraphics.CreateFromHWNDICM(hwnd: hwnd);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFromHWNDICM(hwnd, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGPGraphics.CreateFromImage(image: TGpImage);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  DoFreeInnerObj;
  if image <> nil then
    r := GdipGetImageGraphicsContext(image.GdiInnerObj, Obj)
  else
    r := GdipGetImageGraphicsContext(nil, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGPGraphics.CreateFromWnd(hwnd: hwnd);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFromHWND(hwnd, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGPGraphics.DoFreeInnerObj;
begin
  if GdiInnerObj <> nil then
    GdipDeleteGraphics(GdiInnerObj);
  GdiInnerObj := nil;
end;

procedure TGPGraphics.DrawArc(pen: TGpPen; X, Y, Width, Height, startAngle, sweepAngle: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawArc(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height, startAngle, sweepAngle);
end;

procedure TGPGraphics.DrawArc(pen: TGpPen; X, Y, Width, Height: integer; startAngle, sweepAngle: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawArcI(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height, startAngle, sweepAngle);
end;

procedure TGPGraphics.DrawBezier(pen: TGpPen; x1, y1, x2, y2, x3, y3, x4, y4: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawBezier(GdiInnerObj, pen.GdiInnerObj, x1, y1, x2, y2, x3, y3, x4, y4);
end;

procedure TGPGraphics.DrawBezier(pen: TGpPen; x1, y1, x2, y2, x3, y3, x4, y4: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawBezierI(GdiInnerObj, pen.GdiInnerObj, x1, y1, x2, y2, x3, y3, x4, y4);
end;

procedure TGPGraphics.DrawBeziers(pen: TGpPen; const points: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawBeziers(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawBeziers(pen: TGpPen; const points: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawBeziersI(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawCloseCurve2(pen: TGpPen; const points: TGpPointF; Count: integer; tension: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawClosedCurve2(GdiInnerObj, pen.GdiInnerObj, points, Count, tension);
end;

procedure TGPGraphics.DrawCloseCurve2(pen: TGpPen; const points: TGpPoint; Count: integer; tension: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawClosedCurve2I(GdiInnerObj, pen.GdiInnerObj, points, Count, tension);
end;

procedure TGPGraphics.DrawClosedCurve(pen: TGpPen; const points: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawClosedCurve(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawClosedCurve(pen: TGpPen; const points: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawClosedCurveI(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawCurve(pen: TGpPen; const points: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawCurve(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawCurve2(pen: TGpPen; const points: TGpPointF; Count: integer; tension: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawCurve2(GdiInnerObj, pen.GdiInnerObj, points, Count, tension);
end;

procedure TGPGraphics.DrawCurve2(pen: TGpPen; const points: TGpPoint; Count: integer; tension: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawCurve2I(GdiInnerObj, pen.GdiInnerObj, points, Count, tension);
end;

procedure TGPGraphics.DrawCurve3(pen: TGpPen; const points: TGpPointF; Count, offset, numberOfSegments: integer;
  tension: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawCurve3(GdiInnerObj, pen.GdiInnerObj, points, Count, offset, numberOfSegments, tension);
end;

procedure TGPGraphics.DrawCurve3(pen: TGpPen; const points: TGpPoint; Count, offset, numberOfSegments: integer;
  tension: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawCurve3I(GdiInnerObj, pen.GdiInnerObj, points, Count, offset, numberOfSegments, tension);
end;

procedure TGPGraphics.DrawCurve(pen: TGpPen; const points: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawCurveI(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawEllipse(pen: TGpPen; X, Y, Width, Height: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawEllipse(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.DrawEllipse(pen: TGpPen; X, Y, Width, Height: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawEllipseI(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; X, Y: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawImage(GdiInnerObj, image.GdiInnerObj, X, Y);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; X, Y: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawImageI(GdiInnerObj, image.GdiInnerObj, X, Y);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; X, Y, srcx, srcy, srcwidth, srcheight: single; srcUnit: TUnit);
begin
  if GdiInnerObj <> nil then
    GdipDrawImagePointRect(GdiInnerObj, image.GdiInnerObj, X, Y, srcx, srcy, srcwidth, srcheight, srcUnit);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; X, Y, srcx, srcy, srcwidth, srcheight: integer; srcUnit: TUnit);
begin
  if GdiInnerObj <> nil then
    GdipDrawImagePointRectI(GdiInnerObj, image.GdiInnerObj, X, Y, srcx, srcy, srcwidth, srcheight, srcUnit);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; const dstpoints: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawImagePointsI(GdiInnerObj, image.GdiInnerObj, dstpoints, Count);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; X, Y, Width, Height: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawImageRect(GdiInnerObj, image.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; X, Y, Width, Height: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawImageRectI(GdiInnerObj, image.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.DrawLine(pen: TGpPen; x1, y1, x2, y2: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawLine(GdiInnerObj, pen.GdiInnerObj, x1, y1, x2, y2);
end;

procedure TGPGraphics.DrawLine(pen: TGpPen; x1, y1, x2, y2: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawLineI(GdiInnerObj, pen.GdiInnerObj, x1, y1, x2, y2);
end;

procedure TGPGraphics.DrawLines(pen: TGpPen; const points: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawLines(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawLines(pen: TGpPen; const points: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawLinesI(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawPie(pen: TGpPen; X, Y, Width, Height, startAngle, sweepAngle: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawPie(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height, startAngle, sweepAngle);
end;

procedure TGPGraphics.DrawPie(pen: TGpPen; X, Y, Width, Height: integer; startAngle, sweepAngle: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawPieI(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height, startAngle, sweepAngle);
end;

procedure TGPGraphics.DrawPolygon(pen: TGpPen; const points: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawPolygon(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawPolygon(pen: TGpPen; const points: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawPolygonI(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawRectangle(pen: TGpPen; X, Y, Width, Height: single);
begin
  if GdiInnerObj <> nil then
    GdipDrawRectangle(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.DrawRectangle(pen: TGpPen; X, Y, Width, Height: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawRectangleI(GdiInnerObj, pen.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.DrawRectangle(pen: TGpPen; r: Windows.TRect);
begin
  if GdiInnerObj <> nil then
    GdipDrawRectangleI(GdiInnerObj, pen.GdiInnerObj, r.Left, r.top, r.Width, r.Height);
end;

procedure TGPGraphics.DrawRectangles(pen: TGpPen; const points: TGpRectF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawRectangles(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawRectangles(pen: TGpPen; const points: TGpRect; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawRectanglesI(GdiInnerObj, pen.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.DrawString(s: string; font: TGpFont; const layoutRect: TRectF;
  stringFormat: TGpStringFormat; brush: TGpBrush);
var
  f: Pointer;
  sf: Pointer;
  b: TGpBrush;
  // R: TGDIPLUS_STATUS;
begin
  if GdiInnerObj <> nil then
  begin
    if (font <> nil) and (font.GdiInnerObj <> nil) then
      f := font.GdiInnerObj
    else
      f := nil;
    if (stringFormat <> nil) and (stringFormat.GdiInnerObj <> nil) then
      sf := stringFormat.GdiInnerObj
    else
      sf := nil;
    if (brush <> nil) and (brush.GdiInnerObj <> nil) then
      b := brush.GdiInnerObj
    else
      b := nil;
    GdipDrawString(GdiInnerObj, s, Length(s), f, layoutRect, sf, b);
  end;
end;

procedure TGPGraphics.FillClosedCurve(brush: TGpBrush; const points: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillClosedCurve(GdiInnerObj, brush.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.FillClosedCurve2(brush: TGpBrush; const points: TGpPointF; Count: integer;
  tension: single; fillMode: TGpFillMode);
begin
  if GdiInnerObj <> nil then
    GdipFillClosedCurve2(GdiInnerObj, brush.GdiInnerObj, points, Count, tension, fillMode);
end;

procedure TGPGraphics.FillClosedCurve2(brush: TGpBrush; const points: TGpPoint; Count: integer;
  tension: single; fillMode: TGpFillMode);
begin
  if GdiInnerObj <> nil then
    GdipFillClosedCurve2I(GdiInnerObj, brush.GdiInnerObj, points, Count, tension, fillMode);
end;

procedure TGPGraphics.FillClosedCurve(brush: TGpBrush; const points: TGpPoint; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillClosedCurveI(GdiInnerObj, brush.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.FillEllipse(brush: TGpBrush; X, Y, Width, Height: single);
begin
  if GdiInnerObj <> nil then
    GdipFillEllipse(GdiInnerObj, brush.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.FillEllipse(brush: TGpBrush; X, Y, Width, Height: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillEllipseI(GdiInnerObj, brush.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.FillPie(brush: TGpBrush; X, Y, Width, Height, startAngle, sweepAngle: single);
begin
  if GdiInnerObj <> nil then
    GdipFillPie(GdiInnerObj, brush.GdiInnerObj, X, Y, Width, Height, startAngle, sweepAngle);
end;

procedure TGPGraphics.FillPie(brush: TGpBrush; X, Y, Width, Height: integer; startAngle, sweepAngle: single);
begin
  if GdiInnerObj <> nil then
    GdipFillPieI(GdiInnerObj, brush.GdiInnerObj, X, Y, Width, Height, startAngle, sweepAngle);
end;

procedure TGPGraphics.FillPolygon(brush: TGpBrush; const points: TGpPointF; Count: integer; fillMode: TGpFillMode);
begin
  if GdiInnerObj <> nil then
    GdipFillPolygon(GdiInnerObj, brush.GdiInnerObj, points, Count, fillMode);
end;

procedure TGPGraphics.FillPolygon(brush: TGpBrush; const points: TGpRectF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillPolygon2(GdiInnerObj, brush.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.FillPolygon(brush: TGpBrush; const points: TGpRect; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillPolygon2I(GdiInnerObj, brush.GdiInnerObj, points, Count);
end;

procedure TGPGraphics.FillPolygon(brush: TGpBrush; const points: TGpPoint; Count: integer; fillMode: TGpFillMode);
begin
  if GdiInnerObj <> nil then
    GdipFillPolygonI(GdiInnerObj, brush.GdiInnerObj, points, Count, fillMode);
end;

procedure TGPGraphics.FillRectangle(brush: TGpBrush; X, Y, Width, Height: single);
begin
  if GdiInnerObj <> nil then
    GdipFillRectangle(GdiInnerObj, brush.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.FillRectangle(brush: TGpBrush; X, Y, Width, Height: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillRectangleI(GdiInnerObj, brush.GdiInnerObj, X, Y, Width, Height);
end;

procedure TGPGraphics.FillRectangles(brush: TGpBrush; const rects: TGpRectF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillRectangles(GdiInnerObj, brush.GdiInnerObj, rects, Count);
end;

procedure TGPGraphics.FillRectangles(brush: TGpBrush; const rects: TGpRect; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipFillRectanglesI(GdiInnerObj, brush.GdiInnerObj, rects, Count);
end;

procedure TGPGraphics.DrawImage(image: TGpImage; const dstpoints: TGpPointF; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipDrawImagePoints(GdiInnerObj, image.GdiInnerObj, dstpoints, Count);
end;

function TGPGraphics.GetCompositingMode: TCompositingMode;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetCompositingMode(GdiInnerObj, Result) <> Ok then
      Result := CompositingModeSourceOver;
  end;
end;

function TGPGraphics.GetCompositingQuality: TCompositingQuality;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetCompositingQuality(GdiInnerObj, Result) <> Ok then
      Result := CompositingQualityInvalid;
  end;
end;

function TGPGraphics.GetDC: HDC;
begin
  if GdiInnerObj <> nil then
    GdipGetDC(GdiInnerObj, Result)
  else
    Result := 0;
end;

function TGPGraphics.GetDpiX: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetDpiX(GdiInnerObj, Result);
end;

function TGPGraphics.GetDpiY: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetDpiY(GdiInnerObj, Result);
end;

function TGPGraphics.GetInterpolationMode: TInterpolationMode;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetInterpolationMode(GdiInnerObj, Result) <> Ok then
      Result := InterpolationModeInvalid;
  end;
end;

function TGPGraphics.GetPageScale: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetPageScale(GdiInnerObj, Result);
end;

function TGPGraphics.GetPageUnit: TUnit;
begin
  Result := UnitWorld;
  if GdiInnerObj <> nil then
    GdipGetPageUnit(GdiInnerObj, Result);
end;

function TGPGraphics.GetPixelOffsetMode: TPixelOffsetMode;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetPixelOffsetMode(GdiInnerObj, Result) <> Ok then
      Result := PixelOffsetModeInvalid;
  end;
end;

procedure TGPGraphics.GetRenderingOrigin(var X, Y: integer);
begin
  if GdiInnerObj <> nil then
    GdipGetRenderingOrigin(self.GdiInnerObj, X, Y)
  else
  begin
    X := 0;
    Y := 0;
  end;
end;

function TGPGraphics.GetSmoothingMode: TSmoothingMode;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetSmoothingMode(GdiInnerObj, Result) <> Ok then
      Result := SmoothingModeInvalid;
  end;
end;

function TGPGraphics.GetTextContrast: UINT;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetTextContrast(GdiInnerObj, Result) <> Ok then
      Result := 0;
  end;
end;

function TGPGraphics.GetTextRenderingHint: TTextRenderingHint;
begin
  if GdiInnerObj <> nil then
  begin
    if GdipGetTextRenderingHint(GdiInnerObj, Result) <> Ok then
      Result := TextRenderingHintSystemDefault;
  end;
end;

procedure TGPGraphics.GraphicsClear(color: TARGB);
begin
  if GdiInnerObj <> nil then
    GdipGraphicsClear(GdiInnerObj, color);
end;

procedure TGPGraphics.MeasureString(s: string; font: TGpFont; const layoutRect: TRectF;
  stringFormat: TGpStringFormat; var boundingBox: TRectF);
var
  codepointsFitted, linesFilled: integer;
begin
  if (font <> nil) and (stringFormat <> nil) then
    GdipMeasureString(GdiInnerObj, s, Length(s), font.GdiInnerObj, layoutRect, stringFormat.GdiInnerObj, boundingBox,
      codepointsFitted, linesFilled)
  else
  begin
    FillChar(boundingBox, SizeOf(boundingBox), 0);
    codepointsFitted := 0;
    linesFilled := 0;
  end;
end;

procedure TGPGraphics.ReleaseDC(HDC: HDC);
begin
  if GdiInnerObj <> nil then
    GdipReleaseDC(GdiInnerObj, HDC);
end;

procedure TGPGraphics.ResetPageTransform;
begin
  if GdiInnerObj <> nil then
    GdipResetPageTransform(GdiInnerObj);
end;

procedure TGPGraphics.ResetWorldTransform;
begin
  if GdiInnerObj <> nil then
    GdipResetWorldTransform(GdiInnerObj);
end;

procedure TGPGraphics.SetCompositingMode(const Value: TCompositingMode);
begin
  if GdiInnerObj <> nil then
    GdipSetCompositingMode(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetCompositingQuality(const Value: TCompositingQuality);
begin
  if GdiInnerObj <> nil then
    GdipSetCompositingQuality(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetInterpolationMode(const Value: TInterpolationMode);
begin
  if GdiInnerObj <> nil then
    GdipSetInterpolationMode(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetPageScale(const Value: single);
begin
  if GdiInnerObj <> nil then
    GdipSetPageScale(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetPageUnit(const Value: TUnit);
begin
  if GdiInnerObj <> nil then
    GdipSetPageUnit(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetPixelOffsetMode(const Value: TPixelOffsetMode);
begin
  if GdiInnerObj <> nil then
    GdipSetPixelOffsetMode(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetRenderingOrigin(X, Y: integer);
begin
  if GdiInnerObj <> nil then
    GdipSetRenderingOrigin(GdiInnerObj, X, Y);
end;

procedure TGPGraphics.SetSmoothingMode(const Value: TSmoothingMode);
begin
  if GdiInnerObj <> nil then
    GdipSetSmoothingMode(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetTextContrast(const Value: UINT);
begin
  if GdiInnerObj <> nil then
    GdipSetTextContrast(GdiInnerObj, Value);
end;

procedure TGPGraphics.SetTextRenderingHint(const Value: TTextRenderingHint);
begin
  if GdiInnerObj <> nil then
    GdipSetTextRenderingHint(GdiInnerObj, Value);
end;

function TGPGraphics.StringWidth(s: string; font: TGpFont; const layoutRect: TRectF;
  stringFormat: TGpStringFormat): single;
var
  f: Pointer;
  sf: Pointer;
  r: TGDIPLUS_STATUS;
  bb: TRectF;
  cf, lf: integer;
begin
  if GdiInnerObj <> nil then
  begin
    if (font <> nil) and (font.GdiInnerObj <> nil) then
      f := font.GdiInnerObj
    else
      f := nil;
    if (stringFormat <> nil) and (stringFormat.GdiInnerObj <> nil) then
      sf := stringFormat.GdiInnerObj
    else
      sf := nil;
    r := GdipMeasureString(GdiInnerObj, s, Length(s), f, layoutRect, sf, bb, cf, lf);
    if r = Ok then
      Result := bb.Width
    else
      Result := 0;
  end
  else
    Result := 0;
end;

procedure TGPGraphics.DrawImage(image: TGpImage; dst: TGpRect; srcx, srcy, srcwidth, srcheight: integer;
  imageAttributes: TGPImageAttributes; srcUnit: TUnit);
var
  r: TGDIPLUS_STATUS;
begin
  if (GdiInnerObj <> nil) and (image <> nil) and (image.GdiInnerObj <> nil) then
  begin
    if (imageAttributes <> nil) and imageAttributes.InnerObjValid then
      r := GdipDrawImageRectRectI(GdiInnerObj, image.GdiInnerObj, dst.X, dst.Y, dst.Width,
        dst.Height, srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes.GdiInnerObj, nil, nil)
    else
      r := GdipDrawImageRectRectI(GdiInnerObj, image.GdiInnerObj, dst.X, dst.Y, dst.Width,
        dst.Height, srcx, srcy, srcwidth, srcheight, srcUnit, nil, nil, nil);
  end;
end;

{ TGpPen }

procedure TGpPen.CreatePen1(color: TARGB; Width: single; u: TUnit);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreatePen1(color, Width, u, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGpPen.CreatePen2(brush: TGpBrush; Width: single; u: TUnit);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
  begin
    DoFreeInnerObj;
    GdiInnerObj := nil;
  end;
  if brush.GdiInnerObj <> nil then
  begin
    r := GdipCreatePen2(brush.GdiInnerObj, Width, u, Obj);
    if r = Ok then
      GdiInnerObj := Obj;
  end;
end;

function TGpPen.DoClone(var Obj: Pointer): TGpStatus;
begin
  Result := GdipClonePen(GdiInnerObj, Obj);
end;

procedure TGpPen.DoFreeInnerObj;
begin
  GdipDeletePen(GdiInnerObj);
end;

function TGpPen.GetCustomStartCap: TGpCustomLineCap;
begin
  Result := nil;
  if GdiInnerObj <> nil then
    GdipGetPenCustomStartCap(GdiInnerObj, Result);
end;

function TGpPen.GetPenDashCap197819: TGpDashCap;
begin
  Result := DashCapFlat;
  if GdiInnerObj <> nil then
    GdipGetPenDashCap197819(GdiInnerObj, Result);
end;

function TGpPen.GetPenEndCap: TGpLineCap;
begin
  Result := LineCapFlat;
  if GdiInnerObj <> nil then
    GdipGetPenEndCap(GdiInnerObj, Result);
end;

function TGpPen.GetPenLineJoin: TGpLineJoin;
begin
  Result := LineJoinMiter;
  if GdiInnerObj <> nil then
    GdipGetPenLineJoin(GdiInnerObj, Result);
end;

function TGpPen.GetPenStartCap: TGpLineCap;
begin
  Result := LineCapFlat;
  if GdiInnerObj <> nil then
    GdipGetPenStartCap(GdiInnerObj, Result);
end;

function TGpPen.GetPenUnit: TUnit;
begin
  Result := UnitWorld;
  if GdiInnerObj <> nil then
    GdipGetPenUnit(GdiInnerObj, Result);
end;

function TGpPen.GetPenWidth: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetPenWidth(GdiInnerObj, Result);
end;

procedure TGpPen.SetCustomStartCap(const Value: TGpCustomLineCap);
begin
  if GdiInnerObj <> nil then
    GdipSetPenCustomStartCap(GdiInnerObj, Value);
end;

procedure TGpPen.SetPenDashCap197819(const Value: TGpDashCap);
begin
  if GdiInnerObj <> nil then
    GdipSetPenDashCap197819(GdiInnerObj, Value);
end;

procedure TGpPen.SetPenEndCap(const Value: TGpLineCap);
begin
  if GdiInnerObj <> nil then
    GdipSetPenEndCap(GdiInnerObj, Value);
end;

procedure TGpPen.SetPenLineJoin(const Value: TGpLineJoin);
begin
  if GdiInnerObj <> nil then
    GdipSetPenLineJoin(GdiInnerObj, Value);
end;

procedure TGpPen.SetPenStartCap(const Value: TGpLineCap);
begin
  if GdiInnerObj <> nil then
    GdipSetPenStartCap(GdiInnerObj, Value);
end;

procedure TGpPen.SetPenUnit(const Value: TUnit);
begin
  if GdiInnerObj <> nil then
    GdipSetPenUnit(GdiInnerObj, Value);
end;

procedure TGpPen.SetPenWidth(const Value: single);
begin
  if GdiInnerObj <> nil then
    GdipSetPenWidth(GdiInnerObj, Value);
end;

{ TGpBrush }

function TGpBrush.DoClone(var Obj: Pointer): TGpStatus;
begin
  Result := GdipCloneBrush(GdiInnerObj, Obj);
end;

procedure TGpBrush.DoFreeInnerObj;
begin
  GdipDeleteBrush(GdiInnerObj);
end;

{ TGpImage }

procedure TGpImage.BitmapLockBits(const rect: TGpRect; flags: UINT; format: TPixelFormat;
  var lockedBitmapData: TBitmapData);
begin
  if GdiInnerObj <> nil then
    GdipBitmapLockBits(GdiInnerObj, rect, flags, format, lockedBitmapData);
end;

procedure TGpImage.BitmapUnlockBits(const lockedBitmapData: TBitmapData);
begin
  if GdiInnerObj <> nil then
    GdipBitmapUnlockBits(GdiInnerObj, lockedBitmapData);
end;

procedure TGpImage.CreateBitmap(Width, Height: integer; format: TPixelFormat);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  r := GdipCreateBitmapFromScan0(Width, Height, 0, format, nil, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpImage.CreateBitmap(Width, Height, stride: integer; format: TPixelFormat; scan0: pbyte);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  r := GdipCreateBitmapFromScan0(Width, Height, stride, format, scan0, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpImage.DisposeImage;
begin
  DoFreeInnerObj;
end;

function TGpImage.DoClone(var Obj: Pointer): TGpStatus;
begin
  Result := GdipCloneImage(GdiInnerObj, Obj);
end;

procedure TGpImage.DoFreeInnerObj;
begin
  UnLockImage;
  SetLength(FPropertyIDs, 0);
  GdipDisposeImage(GdiInnerObj);
  GdiInnerObj := nil;
  FImageCount := -1;
  FWidth := 0;
  FHeight := 0;
  if FImageDelays <> nil then
  begin
    FreeMem(FImageDelays);
    FImageDelays := nil;
  end;
end;

function TGpImage.GetImageBuf: pchar;
begin
  Result := FLockedData.Scan;
end;

function TGpImage.GetImageCount: integer;
begin
  if FImageCount = -1 then
    GetImageFrameCount;
  Result := FImageCount;
end;

function TGpImage.GetImageDelay(Index: integer): integer;
var
  tmp: PInteger;
begin
  if FImageDelays <> nil then
  begin
    tmp := FImageDelays.Value;
    Inc(tmp, Index);
    Result := tmp^;
  end
  else
    Result := 0;
end;

function TGpImage.GetImageFlags: UINT;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetImageFlags(GdiInnerObj, Result);
end;

procedure TGpImage.GetImageFrameCount;
var
  C: longword;
  tmp: PGUID;
begin
  if (GdiInnerObj <> nil) and (GdipImageGetFrameDimensionsCount(GdiInnerObj, integer(C)) = Ok) and (C >= 1) then
  begin
    GetMem(tmp, C * SizeOf(TGUID));
    if tmp <> nil then
    begin
      if GdipImageGetFrameDimensionsList(GdiInnerObj, tmp^, C) = Ok then
      begin
        FImageGUID := tmp^;
        if GdipImageGetFrameCount(GdiInnerObj, tmp^, integer(C)) = Ok then
        begin
          FImageCount := C;
          if GdipGetPropertyItemSize(GdiInnerObj, PropertyTagFrameDelay, C) = Ok then
          begin
            if FImageDelays <> nil then
              FreeMem(FImageDelays);
            GetMem(FImageDelays, C);
            if FImageDelays <> nil then
              GdipGetPropertyItem(GdiInnerObj, PropertyTagFrameDelay, C, FImageDelays);
          end;
        end;
      end;
      FreeMem(tmp);
    end;
  end;
end;

function TGpImage.GetImageHeight: UINT;
begin
  Result := FHeight;
  if (Result = 0) and (GdiInnerObj <> nil) then
    GdipGetImageHeight(GdiInnerObj, Result);
end;

function TGpImage.GetImageHorizontalResolution: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetImageHorizontalResolution(GdiInnerObj, Result);
end;

procedure TGpImage.GetImageInfo;
begin
  FWidth := ImageWidth;
  FHeight := ImageHeight;
  GetImageFrameCount;
end;

function TGpImage.GetImagePixelFormat: TPixelFormat;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetImagePixelFormat(GdiInnerObj, Result);
end;

function TGpImage.GetImageRawFormat: TGUID;
begin
  FillChar(Result, SizeOf(Result), 0);
  if GdiInnerObj <> nil then
    GdipGetImageRawFormat(GdiInnerObj, Result);
end;

function TGpImage.GetImageStride: longword;
begin
  Result := FLockedData.stride;
end;

function TGpImage.GetImageType: TImageType;
begin
  Result := ImageTypeUnknown;
  if GdiInnerObj <> nil then
    GdipGetImageType(GdiInnerObj, Result);
end;

function TGpImage.GetImageVerticalResolution: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetImageVerticalResolution(GdiInnerObj, Result);
end;

function TGpImage.GetImageWidth: UINT;
begin
  Result := FWidth;
  if (Result = 0) and (GdiInnerObj <> nil) then
    GdipGetImageWidth(GdiInnerObj, Result);
end;

function TGpImage.GetLockData: PBitmapData;
begin
  Result := @FLockedData;
end;

function TGpImage.GetLocked: boolean;
begin
  Result := FLockedData.Scan <> nil;
end;

function TGpImage.GetPixel(X, Y: longword): TARGB;
var
  P: pchar;
  ptmp: PARGB absolute P;
begin
  if Locked and (X < ImageWidth) and (Y < ImageHeight) then
  begin
    P := FLockedData.Scan;
    P := P + Y * FLockedData.stride + X * FBytePerPix;
    if (X = ImageWidth - 1) and (Y = ImageHeight - 1) then
    begin
      Result.argb := 0;
    end
    else
      Result := ptmp^;
  end
  else
    Result.argb := 0;
end;

function TGpImage.GetPixIncrement: longword;
begin
  case FLockedData.PixelFormat of
    PixelFormat24bppRGB:
      Result := 3;
    PixelFormat8bppIndexed:
      Result := 1;
    else
      Result := 4;
  end;
end;

function TGpImage.GetPropertyCount: longword;
begin
  if InnerObjValid then
  begin
    if GdipGetPropertyCount(GdiInnerObj, Result) = Ok then
    begin
      SetLength(FPropertyIDs, Result);
      GdipGetPropertyIdList(GdiInnerObj, Result, FPropertyIDs[0]);
    end;
  end
  else
    Result := 0;
end;

function TGpImage.GetPropertyID(Index: integer): longword;
begin
  if (index >= 0) and (index < Length(FPropertyIDs)) then
    Result := FPropertyIDs[index]
  else
    Result := 0;
end;

function TGpImage.GetPropertyValue(PID: longword; var Len: longword): Pointer;
var
  ppi: TPROPERTY_ITEM;
begin
  Len := 0;
  Result := nil;
  if GdipGetPropertyItemSize(GdiInnerObj, PID, Len) = Ok then
  begin
    if GdipGetPropertyItem(GdiInnerObj, PID, Len, @ppi) = Ok then
      Result := ppi.Value;
  end;
end;

function TGpImage.GetRotateFlipType: TRotateFlipType;
var
  sz: UINT;
  pbuf: array [0 .. 29] of ansichar;
begin
  Result := RotateNoneFlipNone;
  if InnerObjValid then
  begin
    if GdipGetPropertyItemSize(GdiInnerObj, PropertyTagOrientation, sz) = Ok then
    begin
      if GdipGetPropertyItem(GdiInnerObj, PropertyTagOrientation, sz, @pbuf) = Ok then
        case pbyte(PPROPERTY_ITEM(@pbuf).Value)^ of
          1:
            Result := RotateNoneFlipNone;
          2:
            Result := RotateNoneFlipX;
          3:
            Result := Rotate180FlipNone;
          4:
            Result := Rotate180FlipX;
          5:
            Result := Rotate90FlipX;
          6:
            Result := Rotate90FlipNone;
          7:
            Result := Rotate270FlipX;
          8:
            Result := Rotate270FlipNone;
        end;
    end;
  end;
end;

procedure TGpImage.LoadImageFromFile(filename: string);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  DoFreeInnerObj;
  r := GdipLoadImageFromFile(filename, Obj);
  if r = Ok then
  begin
    GdiInnerObj := Obj;
    GetImageInfo;
  end
  else
  begin
    SetGPStatus(r);
    DoFreeInnerObj;
  end;
end;

procedure TGpImage.LoadImageFromFileICM(filename: string);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipLoadImageFromFileICM(filename, Obj);
  if r = Ok then
  begin
    GdiInnerObj := Obj;
    GetImageInfo;
  end;
end;

procedure TGpImage.LoadImageFromStream(stream: IStream);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  r := GdipLoadImageFromStream(stream, Obj);
  if r = Ok then
  begin
    GdiInnerObj := Obj;
    GetImageInfo;
  end;
end;

procedure TGpImage.LoadImageFromStreamICM(stream: IStream);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  r := GdipLoadImageFromStreamICM(stream, Obj);
  if r = Ok then
  begin
    GdiInnerObj := Obj;
    GetImageInfo;
  end;
end;

function TGpImage.LockImage: boolean;
var
  r: TRect;
  gs: TGpStatus;
begin
  UnLockImage;
  if GdiInnerObj <> nil then
  begin
    r.X := 0;
    r.Y := 0;
    r.Width := ImageWidth;
    r.Height := ImageHeight;
    // GetMem(FLockedData.Scan, r.Width * r.Height * 4);
    gs := GdipBitmapLockBits(GdiInnerObj, r, ImageLockModeRead, ImagePixelFormat, FLockedData);
    Result := gs = Ok;
    if Result then
      case FLockedData.PixelFormat of
        PixelFormat24bppRGB:
          FBytePerPix := 3;
        PixelFormat8bppIndexed:
          FBytePerPix := 1;
        else
          FBytePerPix := 4;
      end;
  end
  else
    Result := False;
end;

procedure TGpImage.RotateFlip(rfType: TRotateFlipType);
var
  r: TGpStatus;
begin
  if InnerObjValid then
  begin
    r := GdipImageRotateFlip(GdiInnerObj, rfType);
    if r = Ok then
    begin
      FWidth := 0;
      FHeight := 0;
    end
    else
      DbgPrint('RotateFlip result %d', [integer(r)]);
  end;
end;

function TGpImage.SaveImageToFile(filename: string; const clsidEncoder: TGUID;
  encoderParams: PEncoderParameters): boolean;
var
  P: TEncoderParameters;
  Q: longword;
begin
  Result := False;
  if GdiInnerObj <> nil then
  begin
    if encoderParams = nil then
    begin
      P.Count := 1;
      P.Parameters[0].ParameterGUID := GUID_Quality;
      P.Parameters[0].NumberOfValues := 1;
      P.Parameters[0].EncoderParameterValueType := SizeOf(longword);
      Q := 95;
      P.Parameters[0].Value := @Q;
      encoderParams := @P;
    end;
    Result := GdipSaveImageToFile(GdiInnerObj, filename, clsidEncoder, encoderParams) = Ok;
    if not Result then
      DbgPrint('Save image fail');
  end;
end;

procedure TGpImage.SetImageActiveFrame(const Value: integer);
begin
  if (FImageCount >= 1) and (Value < FImageCount) then
  begin
    GdipImageSelectActiveFrame(GdiInnerObj, FImageGUID, Value);
    FImageActiveFrame := Value;
  end;
end;

procedure TGpImage.SetRotateFlipType(const Value: TRotateFlipType);
var
  pi: TPROPERTY_ITEM;
begin
  if InnerObjValid then
  begin
    pi.id := PropertyTagOrientation;
    // pi.Length :=;
    // GdipSetPropertyItem();
  end;
end;

procedure TGpImage.UnLockImage;
begin
  if FLockedData.Scan <> nil then
  begin
    // FreeMem(FLockedData.Scan);
    BitmapUnlockBits(FLockedData);
  end;
  FillChar(FLockedData, SizeOf(FLockedData), 0);
end;

procedure TGpImage.CreateBitmap(Width, Height: integer; target: TGPGraphics);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  if target <> nil then
    r := GdipCreateBitmapFromGraphics(Width, Height, target.GdiInnerObj, Obj)
  else
    r := GdipCreateBitmapFromGraphics(Width, Height, nil, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpImage.CreateBitmap(const bmi: TBITMAPINFO; gdiBitMapData: Pointer);
var
  id: Pointer;
begin
  Return;
  if GdipCreateBitmapFromGdiDib(bmi, gdiBitMapData, id) = Ok then
    GdiInnerObj := id;
end;

procedure TGpImage.CreateBitmap(hbm: HBITMAP; hpal: HPALETTE);
var
  id: Pointer;
begin
  Return;
  if GdipCreateBitmapFromHBITMAP(hbm, hpal, id) = Ok then
    GdiInnerObj := id;
end;

{ TGpSolidBrush }

procedure TGpSolidBrush.CreateBrush(color: TARGB);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  GdiInnerObj := nil;
  r := GdipCreateSolidFill(color, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

function TGpSolidBrush.GetColor: TARGB;
begin
  Result.argb := 0;
  if GdiInnerObj <> nil then
    GdipGetSolidFillColor(GdiInnerObj, Result);
end;

procedure TGpSolidBrush.SetColor(const Value: TARGB);
begin
  if GdiInnerObj <> nil then
    GdipSetSolidFillColor(GdiInnerObj, Value);
end;

{ TGpLineBrush }

procedure TGpLineBrush.CreateLineBrush(const point1, point2: TGpPointF; color1, color2: TARGB; wrapMode: TGpWrapMode);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  GdiInnerObj := nil;
  r := GdipCreateLineBrush(point1, point2, color1, color2, wrapMode, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpLineBrush.CreateLineBrushFromRect(const rect: TGpRectF; color1, color2: TARGB;
  mode: TLinearGradientMode; wrapMode: TGpWrapMode);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Return;
  GdiInnerObj := nil;
  r := GdipCreateLineBrushFromRect(rect, color1, color2, mode, wrapMode, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpLineBrush.CreateLineBrushFromRectI(const rect: TGpRect; color1, color2: TARGB;
  mode: TLinearGradientMode; wrapMode: TGpWrapMode);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateLineBrushFromRectI(rect, color1, color2, mode, wrapMode, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpLineBrush.CreateLineBrushFromRectWithAngle(const rect: TGpRectF; color1, color2: TARGB;
  angle: single; isAngleScalable: boolean; wrapMode: TGpWrapMode);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateLineBrushFromRectWithAngle(rect, color1, color2, angle, isAngleScalable, wrapMode, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpLineBrush.CreateLineBrushFromRectWithAngleI(const rect: TGpRect; color1, color2: TARGB;
  angle: single; isAngleScalable: boolean; wrapMode: TGpWrapMode);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateLineBrushFromRectWithAngleI(rect, color1, color2, angle, isAngleScalable, wrapMode, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpLineBrush.CreateLineBrush(const point1, point2: TGpPoint; color1, color2: TARGB; wrapMode: TGpWrapMode);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateLineBrushI(point1, point2, color1, color2, wrapMode, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpLineBrush.GetLineBlend(var blend, positions: single; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipGetLineBlend(GdiInnerObj, blend, positions, Count);
end;

function TGpLineBrush.GetLineBlendCount: integer;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetLineBlendCount(GdiInnerObj, Result);
end;

function TGpLineBrush.GetLineColors: TARGB;
begin
  Result.argb := 0;
  if GdiInnerObj <> nil then
    GdipGetLineColors(GdiInnerObj, Result);
end;

function TGpLineBrush.GetLineGammaCorrection: boolean;
var
  b: BOOL;
begin
  Result := False;
  if GdiInnerObj <> nil then
  begin
    GdipGetLineGammaCorrection(GdiInnerObj, b);
    Result := b;
  end;
end;

function TGpLineBrush.GetLineRect: TGpRectF;
begin
  Result.X := 0;
  Result.Y := 0;
  Result.Width := 0;
  Result.Height := 0;
  if GdiInnerObj <> nil then
    GdipGetLineRect(GdiInnerObj, Result);
end;

function TGpLineBrush.GetLineRectI: TGpRect;
begin
  Result.X := 0;
  Result.Y := 0;
  Result.Width := 0;
  Result.Height := 0;
  if GdiInnerObj <> nil then
    GdipGetLineRectI(GdiInnerObj, Result);
end;

function TGpLineBrush.GetLineTransform: TGpMatrix;
begin
  Result := nil;
  if GdiInnerObj <> nil then
    GdipGetLineTransform(GdiInnerObj, Result);
end;

function TGpLineBrush.GetLineWrapMode: TGpWrapMode;
begin
  Result := WrapModeTile;
  if GdiInnerObj <> nil then
    GdipGetLineWrapMode(GdiInnerObj, Result);
end;

procedure TGpLineBrush.SetLineBlend(const blend, positions: single; Count: integer);
begin
  if GdiInnerObj <> nil then
    GdipSetLineBlend(GdiInnerObj, blend, positions, Count);
end;

procedure TGpLineBrush.SetLineColors(color1, color2: TARGB);
begin
  if GdiInnerObj <> nil then
    GdipSetLineColors(GdiInnerObj, color1, color2);
end;

procedure TGpLineBrush.SetLineGammaCorrection(const Value: boolean);
begin
  if GdiInnerObj <> nil then
    GdipSetLineGammaCorrection(GdiInnerObj, Value);
end;

procedure TGpLineBrush.SetLineTransform(const Value: TGpMatrix);
begin
  if GdiInnerObj <> nil then
    GdipSetLineTransform(GdiInnerObj, Value);
end;

procedure TGpLineBrush.SetLineWrapMode(const Value: TGpWrapMode);
begin
  if GdiInnerObj <> nil then
    GdipSetLineWrapMode(GdiInnerObj, Value);
end;

{ TGpBitmap }

procedure TGpBitmap.BitmapLockBits(const rect: TGpRect; flags: UINT; format: TPixelFormat;
  lockedBitmapData: TBitmapData);
begin
  if GdiInnerObj <> nil then
    GdipBitmapLockBits(GdiInnerObj, rect, flags, format, lockedBitmapData);
end;

procedure TGpBitmap.BitmapUnlockBits(lockedBitmapData: TBitmapData);
begin
  if GdiInnerObj <> nil then
    GdipBitmapUnlockBits(GdiInnerObj, lockedBitmapData);
end;

function TGpBitmap.CloneBitmapArea(X, Y, Width, Height: single; format: TPixelFormat): TGpBitmap;
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Result := nil;
  if GdiInnerObj <> nil then
  begin
    GdiInnerObj := nil;
    r := GdipCloneBitmapArea(X, Y, Width, Height, format, GdiInnerObj, Obj);
    if r = Ok then
    begin
      Result := TGpBitmap.Create;
      if Result <> nil then
        Result.GdiInnerObj := Obj
      else;
    end;
  end;
end;

function TGpBitmap.CloneBitmapAreaI(X, Y, Width, Height: integer; format: TPixelFormat): TGpBitmap;
var
  r: TGpStatus;
  Obj: Pointer;
begin
  Result := nil;
  if GdiInnerObj <> nil then
  begin
    GdiInnerObj := nil;
    r := GdipCloneBitmapAreaI(X, Y, Width, Height, format, GdiInnerObj, Obj);
    if r = Ok then
    begin
      Result := TGpBitmap.Create;
      if Result <> nil then
        Result.GdiInnerObj := Obj
      else;
    end;
  end;
end;

procedure TGpBitmap.CreateBitmap(Width, Height: integer; format: TPixelFormat);
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
end;

procedure TGpBitmap.CreateBitmapFromDirectDrawSurface(surface: IDirectDrawSurface7);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromDirectDrawSurface(surface, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromFile(filename: string);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromFile(filename, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromFileICM(filename: string);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromFileICM(filename, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromGdiDib(const gdiBitmapInfo: BITMAPINFO; gdiBitMapData: Pointer);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromGdiDib(gdiBitmapInfo, gdiBitMapData, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromGraphics(Width, Height: integer; target: TGPGraphics);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  if target <> nil then
  begin
    r := GdipCreateBitmapFromGraphics(Width, Height, target.GdiInnerObj, Obj);
    if r = Ok then
      GdiInnerObj := Obj;
  end;
end;

procedure TGpBitmap.CreateBitmapFromHBITMAP(hbm: HBITMAP; hpal: HPALETTE);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromHBITMAP(hbm, hpal, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromHICON(hicon: hicon);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromHICON(hicon, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromResource(hInstance: THandle; lpBitmapName: string);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromResource(hInstance, lpBitmapName, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromScan0(Width, Height, stride: integer; format: TPixelFormat; scan0: pbyte);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromScan0(Width, Height, stride, format, scan0, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromStream(stream: IStream);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromStream(stream, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

procedure TGpBitmap.CreateBitmapFromStreamICM(stream: IStream);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  GdiInnerObj := nil;
  r := GdipCreateBitmapFromStreamICM(stream, Obj);
  if r = Ok then
    GdiInnerObj := Obj;
end;

function TGpBitmap.CreateHBITMAPFromBitmap(background: TARGB): HBITMAP;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipCreateHBITMAPFromBitmap(GdiInnerObj, Result, background);
end;

function TGpBitmap.CreateHICONFromBitmap: hicon;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipCreateHICONFromBitmap(GdiInnerObj, Result);
end;

function TGpBitmap.GetHandle: HBITMAP;
begin
  if InnerObjValid then
    GdipCreateHBITMAPFromBitmap(GdiInnerObj, Result, MakeARGB(0, 0, 0, 0))
  else
    Result := 0;
end;

function TGpBitmap.GetPixel(X, Y: integer): TARGB;
begin
  if GdiInnerObj <> nil then
    GdipBitmapGetPixel(GdiInnerObj, X, Y, Result)
  else
    Result.argb := 0;
end;

procedure TGpBitmap.SetPixel(X, Y: integer; const Value: TARGB);
begin
  if GdiInnerObj <> nil then
    GdipBitmapSetPixel(GdiInnerObj, X, Y, Value);
end;

{ TGpFont }

procedure TGpFont.CreateFont(fontFamily: TGpFontFamily; emSize: single; style: integer; u: TUnit);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFont(fontFamily, emSize, style, u, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGpFont.CreateFont(FontName: string; dc: HDC; Height: integer; Weight: integer);
var
  lf: TLogFontW;
begin
  FillChar(lf, SizeOf(lf), 0);
  lf.lfHeight := Height;
  lf.lfWeight := Weight;
  lf.lfCharSet := 1;
  WStrPCopy(lf.lfFaceName, FontName);
  CreateFontFromLogfont(dc, lf);
end;

procedure TGpFont.CreateFontFromLogfont(dc: HDC; const logfont: LOGFONTW);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFontFromLogfontW(dc, logfont, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGpFont.CreateFromDC(dc: HDC);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateFontFromDC(dc, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

function TGpFont.DoClone(var Obj: Pointer): TGpStatus;
begin
  Result := GdipCloneFont(GdiInnerObj, Obj);
end;

procedure TGpFont.DoFreeInnerObj;
begin
  GdipDeleteFont(GdiInnerObj);
end;

function TGpFont.GetFontFamily: TGpFontFamily;
begin
  Result := nil;
  if GdiInnerObj <> nil then
    GdipGetFamily(GdiInnerObj, Result);
end;

function TGpFont.GetFontHeight(g: TGPGraphics): single;
begin
  Result := 0;
  if (GdiInnerObj <> nil) and (g <> nil) and (g.GdiInnerObj <> nil) then
    GdipGetFontHeight(GdiInnerObj, g.GdiInnerObj, Result);
end;

function TGpFont.GetFontHeightGivenDPI(dpi: single): single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetFontHeightGivenDPI(GdiInnerObj, dpi, Result);
end;

function TGpFont.GetFontSize: single;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetFontSize(GdiInnerObj, Result);
end;

function TGpFont.GetFontStyle: integer;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetFontStyle(GdiInnerObj, Result);
end;

function TGpFont.GetFontUnit: TUnit;
begin
  Result := UnitWorld;
  if GdiInnerObj <> nil then
    GdipGetFontUnit(GdiInnerObj, Result);
end;

procedure TGpFont.GetLogFont(g: TGPGraphics; var logfont: LOGFONTW);
begin
  if (GdiInnerObj <> nil) and (g <> nil) and (g.GdiInnerObj <> nil) then
    GdipGetLogFontW(GdiInnerObj, g.GdiInnerObj, logfont);
end;

procedure TGpFont.GetLogFont(g: TGPGraphics; var logfont: LOGFONTA);
begin
  if (GdiInnerObj <> nil) and (g <> nil) and (g.GdiInnerObj <> nil) then
    GdipGetLogFontA(GdiInnerObj, g.GdiInnerObj, logfont);
end;

{ TGpStringFormat }

procedure TGpStringFormat.CreateStringFormat(formatAttributes: integer; language: LANGID);
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipCreateStringFormat(formatAttributes, language, Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

function TGpStringFormat.DoClone(var Obj: Pointer): TGpStatus;
begin
  Result := GdipCloneStringFormat(GdiInnerObj, Obj);
end;

procedure TGpStringFormat.DoFreeInnerObj;
begin
  GdipDeleteStringFormat(GdiInnerObj);
end;

function TGpStringFormat.GetAlign: TStringAlignment;
begin
  Result := StringAlignmentNear;
  if GdiInnerObj <> nil then
    GdipGetStringFormatAlign(GdiInnerObj, Result);
end;

function TGpStringFormat.GetFlags: integer;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetStringFormatFlags(GdiInnerObj, Result);
end;

function TGpStringFormat.GetHotkeyPrefix: integer;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetStringFormatHotkeyPrefix(GdiInnerObj, Result);
end;

function TGpStringFormat.GetLineAlign: TStringAlignment;
begin
  Result := StringAlignmentNear;
  if GdiInnerObj <> nil then
    GdipGetStringFormatLineAlign(GdiInnerObj, Result);
end;

function TGpStringFormat.GetTabStopCount: integer;
begin
  Result := 0;
  if GdiInnerObj <> nil then
    GdipGetStringFormatTabStopCount(GdiInnerObj, Result);
end;

function TGpStringFormat.GetTrimming: TStringTrimming;
begin
  Result := StringTrimmingNone;
  if GdiInnerObj <> nil then
    GdipGetStringFormatTrimming(GdiInnerObj, Result);
end;

procedure TGpStringFormat.SetAlign(const Value: TStringAlignment);
begin
  if GdiInnerObj <> nil then
    GdipSetStringFormatAlign(GdiInnerObj, Value);
end;

procedure TGpStringFormat.SetFlags(const Value: integer);
begin
  if GdiInnerObj <> nil then
    GdipSetStringFormatFlags(GdiInnerObj, Value);
end;

procedure TGpStringFormat.SetHotkeyPrefix(const Value: integer);
begin
  if GdiInnerObj <> nil then
    GdipSetStringFormatHotkeyPrefix(GdiInnerObj, Value);
end;

procedure TGpStringFormat.SetLineAlign(const Value: TStringAlignment);
begin
  if GdiInnerObj <> nil then
    GdipSetStringFormatLineAlign(GdiInnerObj, Value);
end;

procedure TGpStringFormat.SetTrimming(const Value: TStringTrimming);
begin
  if GdiInnerObj <> nil then
    GdipSetStringFormatTrimming(GdiInnerObj, Value);
end;

procedure TGpStringFormat.StringFormatGetGenericDefault;
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipStringFormatGetGenericDefault(Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

procedure TGpStringFormat.StringFormatGetGenericTypographic;
var
  r: TGpStatus;
  Obj: Pointer;
begin
  if GdiInnerObj <> nil then
    DoFreeInnerObj;
  r := GdipStringFormatGetGenericTypographic(Obj);
  if r = Ok then
    GdiInnerObj := Obj
  else
    GdiInnerObj := nil;
end;

{ TGPImageAttributes }

function TGPImageAttributes.ClearBrushRemapTable: TGpStatus;
begin
  Result := ClearRemapTable(TColorAdjustType.brush);
end;

function TGPImageAttributes.ClearColorKey(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesColorKeys(GdiInnerObj, type_, False, NULLARGB, NULLARGB);
end;

function TGPImageAttributes.ClearColorMatrices(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesColorMatrix(GdiInnerObj, type_, False, nil, nil, ColorMatrixFlagsDefault);
end;

function TGPImageAttributes.ClearColorMatrix(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesColorMatrix(GdiInnerObj, type_, False, nil, nil, ColorMatrixFlagsDefault);
end;

function TGPImageAttributes.ClearGamma(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesGamma(GdiInnerObj, type_, False, 0.0);
end;

function TGPImageAttributes.ClearNoOp(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesNoOp(GdiInnerObj, type_, False);
end;

function TGPImageAttributes.ClearOutputChannel(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesOutputChannel(GdiInnerObj, type_, False, ColorChannelFlagsLast);
end;

function TGPImageAttributes.ClearOutputChannelColorProfile(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesOutputChannelColorProfile(GdiInnerObj, type_, False, '');
end;

function TGPImageAttributes.ClearRemapTable(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesRemapTable(GdiInnerObj, type_, False, 0, nil);
end;

function TGPImageAttributes.ClearThreshold(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesThreshold(GdiInnerObj, type_, False, 0.0);
end;

constructor TGPImageAttributes.Create;
var
  imageAttributes: Pointer;
begin
  if GdipCreateImageAttributes(imageAttributes) = Ok then
    GdiInnerObj := imageAttributes;
end;

function TGPImageAttributes.DoClone(var Obj: Pointer): TGpStatus;
begin
  Result := GdipCloneImageAttributes(GdiInnerObj, Obj);
end;

procedure TGPImageAttributes.DoFreeInnerObj;
begin
  if GdiInnerObj <> nil then
    GdipDisposeImageAttributes(GdiInnerObj);
  inherited;
end;

function TGPImageAttributes.GetAdjustedPalette(colorPalette: PColorPalette;
  colorAdjustType: TColorAdjustType): TGpStatus;
begin
  Result := GdipGetImageAttributesAdjustedPalette(GdiInnerObj, colorPalette, colorAdjustType);
end;

function TGPImageAttributes.ResetImageAttributes(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipResetImageAttributes(GdiInnerObj, type_);
end;

function TGPImageAttributes.SetBrushRemapTable(mapSize: cardinal; map: PColorMap): TGpStatus;
begin
  Result := SetRemapTable(mapSize, map, TColorAdjustType.brush);
end;

function TGPImageAttributes.SetColorKey(colorLow, colorHigh: TGPColor; type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesColorKeys(GdiInnerObj, type_, True, colorLow, colorHigh);
end;

function TGPImageAttributes.SetColorMatrices(const colorMatrix, grayMatrix: TColorMatrix;
  mode: TColorMatrixFlags; type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesColorMatrix(GdiInnerObj, type_, True, @colorMatrix, @grayMatrix, mode);
end;

function TGPImageAttributes.SetColorMatrix(const colorMatrix: TColorMatrix; mode: TColorMatrixFlags;
  type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesColorMatrix(GdiInnerObj, type_, True, @colorMatrix, nil, mode);
end;

function TGPImageAttributes.SetGamma(gamma: single; type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesGamma(GdiInnerObj, type_, True, gamma);
end;

function TGPImageAttributes.SetNoOp(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesNoOp(GdiInnerObj, type_, True);
end;

function TGPImageAttributes.SetOutputChannel(channelFlags: TColorChannelFlags; type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesOutputChannel(GdiInnerObj, type_, True, channelFlags);
end;

function TGPImageAttributes.SetOutputChannelColorProfile(colorProfileFilename: widestring;
  type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesOutputChannelColorProfile(GdiInnerObj, type_, True, colorProfileFilename);
end;

function TGPImageAttributes.SetRemapTable(mapSize: cardinal; map: PColorMap; type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesRemapTable(GdiInnerObj, type_, True, mapSize, map);
end;

function TGPImageAttributes.SetThreshold(threshold: single; type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesThreshold(GdiInnerObj, type_, True, threshold);
end;

function TGPImageAttributes.SetToIdentity(type_: TColorAdjustType): TGpStatus;
begin
  Result := GdipSetImageAttributesToIdentity(GdiInnerObj, type_);
end;

function TGPImageAttributes.SetWrapMode(wrap: TWrapMode; color: TGPColor; clamp: BOOL): TGpStatus;
begin
  Result := GdipSetImageAttributesWrapMode(GdiInnerObj, wrap, color, clamp);
end;

end.
